package cn.redsoft.tools.util;

import static java.util.Objects.requireNonNull;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;

public abstract class FileUtils {
	public static final int buffer_size = 4096;

	public static boolean deleteRecursively(File root) {
		if (root != null && root.exists()) {
			File[] children = root.listFiles();
			if (children != null) {
				for (File child : children) {
					deleteRecursively(child);
				}
			}
			return root.delete();
		}
		return false;
	}

	public static void copyResourcesRecursively(File src, File dest)
			throws IOException {
		requireNonNull(src, "源路径不能为null");
		requireNonNull(dest, "目标路径不能为null");
		copyRecursively(src, dest);
	}

	private static void copyRecursively(File src, File dest) throws IOException {
		if (src.isDirectory()) {
			dest.mkdir();
			File[] list = src.listFiles();
			if (list == null) {
				throw new IOException("Could not list files in directory: "
						+ src);
			}
			for (File entry : list) {
				copyRecursively(entry, new File(dest, entry.getName()));
			}
		} else if (src.isFile()) {
			try {
				dest.createNewFile();
			} catch (IOException ex) {
				IOException ioex = new IOException("创建文件失败: " + dest);
				ioex.initCause(ex);
				throw ioex;
			}
			FileUtils.copy(src, dest);
		} else {
		}
	}

	public static int copyAndCloseStream(InputStream in, OutputStream out)
			throws IOException {
		requireNonNull(in);
		requireNonNull(out);
		try {
			return StreamUtils.copy(in, out);
		} finally {
			if (in != null)
				try {
					in.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			if (out != null)
				try {
					out.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
		}
	}

	public static int copy(File src, File dest) throws FileNotFoundException,
			IOException {
		requireNonNull(src);
		requireNonNull(dest);
		return copyAndCloseStream(new BufferedInputStream(new FileInputStream(
				src)), new BufferedOutputStream(new FileOutputStream(dest)));
	}

	public static void copy(byte[] bytes, File dest) throws IOException {
		requireNonNull(dest);
		requireNonNull(bytes);

		ByteArrayInputStream in = new ByteArrayInputStream(bytes);
		OutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
		copyAndCloseStream(in, out);
	}

	public static byte[] copy2ByteArray(InputStream in) throws IOException {
		requireNonNull(in);
		ByteArrayOutputStream out = new ByteArrayOutputStream(buffer_size);
		copyAndCloseStream(in, out);
		return out.toByteArray();
	}

	public static byte[] copy2ByteArray(File src) throws IOException {
		requireNonNull(src);
		BufferedInputStream dest = new BufferedInputStream(new FileInputStream(
				src));
		return copy2ByteArray(dest);
	}

	public static int copyAndCloseCharacterStream(Reader in, Writer out)
			throws IOException {
		requireNonNull(in);
		requireNonNull(out);
		try {
			return StreamUtils.copy(in, out);
		} finally {
			if (in != null)
				try {
					in.close();
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			if (out != null)
				try {
					out.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
		}
	}

	public void copy(String str, Writer out) throws IOException {
		requireNonNull(str);
		requireNonNull(out);
		try {
			out.write(str);
		} finally {
			if (out != null)
				try {
					out.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
		}
	}

	public String copy2String(Reader in) throws IOException {
		StringWriter out = new StringWriter();
		copyAndCloseCharacterStream(in, out);
		return out.toString();
	}
}
